package com.itcam.tingshu.payment.service.impl;

import com.itcam.tingshu.account.client.RechargeInfoFeignClient;
import com.itcam.tingshu.common.constant.SystemConstant;
import com.itcam.tingshu.common.result.Result;
import com.itcam.tingshu.model.account.RechargeInfo;
import com.itcam.tingshu.model.order.OrderInfo;
import com.itcam.tingshu.order.client.OrderInfoFeignClient;
import com.itcam.tingshu.payment.config.WxPayV3Config;
import com.itcam.tingshu.payment.service.PaymentInfoService;
import com.itcam.tingshu.payment.service.WxPayService;
import com.itcam.tingshu.payment.util.PayUtil;
import com.itcam.tingshu.user.client.UserInfoFeignClient;
import com.itcam.tingshu.vo.user.UserInfoVo;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Autowired
    private PaymentInfoService paymentInfoService;

    @Autowired
    private OrderInfoFeignClient orderInfoFeignClient;

    @Autowired
    private RechargeInfoFeignClient rechargeInfoFeignClient;

    @Autowired
    private WxPayV3Config wxPayV3Config;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private RSAAutoCertificateConfig rsaAutoCertificateConfig;

    @Autowired
    private WxPayService wxPayService;

    /**
     * 微信支付
     * @param paymentType
     * @param orderNo
     * @param userId
     * @return
     */
    @Override
    public Map<String, Object> createJsapi(String paymentType, String orderNo, Long userId) {
        // 创建map集合
        HashMap<String, Object> result = new HashMap<>();
        // 1.orderInfo.orderStatus = 0903 说明这个订单已经取消了。 还能支付么? 不能！
        // 2.根据订单编号，查询当前订单信息。
        // 3.保存当前用户的交易记录. Id, userId , orderNo, amount, createTime ,updateTime , paymentStatus, wxOrderNo == paymentInfo;
        // 充值的时候：recharge_info；
        // 定义一个充值总金额变量
        BigDecimal totalAmount = new BigDecimal("0.00");
        if (paymentType.equals(SystemConstant.PAYMENT_TYPE_ORDER)) {
            // 查询订单信息
            Result<OrderInfo> orderInfoResult = orderInfoFeignClient.getOrderInfo(orderNo);
            OrderInfo orderInfo = orderInfoResult.getData();
            // 判断取消状态时，不生成二维码
            if (orderInfo != null && orderInfo.getOrderStatus().equals(SystemConstant.ORDER_STATUS_CANCEL)) {
                return result;
            }
            totalAmount = orderInfo.getOrderAmount();
        } else {
            // 属于充值业务
            Result<RechargeInfo> rechargeInfoResult = rechargeInfoFeignClient.getRechargeInfo(orderNo);
            RechargeInfo rechargeInfo = rechargeInfoResult.getData();
            totalAmount = rechargeInfo.getRechargeAmount();
        }

        // 保存支付交易记录信息到paymentInfo表中
        this.paymentInfoService.savePaymentInfo(paymentType, userId, orderNo, totalAmount);
        // 创建service对象
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();
        // 即之前下单示例一样，填充下单参数
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        // 总金额：订单或充值，实际金额应该是totalAmount
        amount.setTotal(1);
        request.setAmount(amount);
        request.setAppid(wxPayV3Config.getAppid());
        request.setDescription("测试商品标题");
        request.setNotifyUrl(wxPayV3Config.getNotifyUrl());
        request.setOutTradeNo(orderNo);
        Payer payer = new Payer();
        // 需要远程调用
        Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
        UserInfoVo userInfoVo = userInfoVoResult.getData();
        payer.setOpenid(userInfoVo.getWxOpenId());
        request.setPayer(payer);
        // response包含了调起支付所需参数，可直接用于前端调起支付
        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
        // 给map赋值
        result.put("timeStamp", response.getTimeStamp()); // 时间戳
        result.put("nonceStr", response.getNonceStr()); // 随机字符串
        result.put("package", response.getPackageVal()); // 订单详情扩展字符串
        result.put("signType", response.getSignType()); // 签名方式
        result.put("paySign", response.getPaySign());   // 签名

        // 返回数据
        return result;
    }

    /**
     * 查询支付状态
     * @param orderNo
     * @return
     */
    @Override
    public Transaction queryPayStatus(String orderNo) {
        // 创建对象
        QueryOrderByOutTradeNoRequest outTradeNoRequest = new QueryOrderByOutTradeNoRequest();
        // 赋值
        outTradeNoRequest.setMchid(wxPayV3Config.getMerchantId());
        outTradeNoRequest.setOutTradeNo(orderNo);
        try {
            // 创建service对象
            JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();
            // 调用服务层
            Transaction result = service.queryOrderByOutTradeNo(outTradeNoRequest);
            // 打印交易状态
            System.out.println(result.getTradeState());
            // 返回数据
            return result;
        } catch (ServiceException e) {
            // API返回失败，例如ORDER_NOT_EXISTS
            System.out.printf("code=[%s],message=[%s]\n", e.getErrorCode(), e.getErrorMessage());
            System.out.printf("response body=[%s]\n", e.getResponseBody());
        }
        // 默认返回
        return null;
    }

    /**
     * 微信异步回调
     * @param request
     * @return
     */
    @Override
    public Transaction wxNofity(HttpServletRequest request) {
        // 微信支付平台证书的序列号
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        // 签名中的随机数
        String wechatPayNonce = request.getHeader("Wechatpay-Nonce");
        // 应答的微信支付签名
        String wechatSignature = request.getHeader("Wechatpay-Signature");
        // 签名中的时间戳
        String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
        // 请求体body
        String requestBody = PayUtil.readData(request);
        // 构造RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(wechatPayNonce)
                .signature(wechatSignature)
                .timestamp(wechatTimestamp)
                .body(requestBody)
                .build();
        // 初始化NotificationParser
        NotificationParser notificationParser = new NotificationParser();
        try {
            // 以支付通知回调为例、验签、解密并转换成Transaction
            Transaction transaction = notificationParser.parse(requestParam, Transaction.class);
            // 返回数据
            return transaction;
        } catch (ValidationException e) {
            // 签名验证失败，返回401状态码
            log.error("sign verification failed", e);
        }
        return null;
    }


}
